package com.rongc.client.core.network.api;

import android.util.Log;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyLog;
import com.android.volley.error.AuthFailureError;
import com.android.volley.error.NoConnectionError;
import com.android.volley.error.ParseError;
import com.android.volley.error.ServerError;
import com.android.volley.error.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.rongc.client.core.exception.HeaderCodeError;
import com.rongc.client.core.gson.GsonHelper;
import com.rongc.client.core.network.code.HandleCode;
import com.rongc.client.core.utils.ActivityUtils;
import com.rongc.client.core.utils.LogUtils;
import com.rongc.client.core.utils.NetworkUtils;
import com.rongc.client.freight.UniApplication;

import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.rongc.client.core.network.api.AbsRequest.MY_SOCKET_TIMEOUT_MS;

/**
 * 功能：
 *
 * @author yanzi E-mail: yanzi1225627@163.com
 * @version 创建时间: 2015-08-09 下午4:32
 */
public class MultipartRequest<PARAMS extends Map<String, String>, RESULT> extends Request<RESULT> {
    private Class<RESULT> mClass;
    private MultipartEntity entity = new MultipartEntity();

    private Response.Listener<RESULT> mListener;

    private List<File> mFileParts;
    private List<String> mFilePartNames;
    private Map<String, String> mParams;
    private String url;
    /**
     * 单个文件＋参数 上传
     *
     * @param url
     * @param listener
     * @param errorListener
     * @param filePartName
     * @param file
     * @param params
     */
    public MultipartRequest(String url, Response.Listener<RESULT> listener, Response.ErrorListener errorListener,
                            String filePartName, File file, Map<String, String> params, Class<RESULT> clazz) {
        super(Method.POST, url, errorListener);
        LogUtils.i("juner request url: " + url + " request params: " + GsonHelper.writeValue(params));
        mFileParts = new ArrayList<File>();
        if (file != null && file.exists()) {
            mFileParts.add(file);
        } else {
            VolleyLog.e("MultipartRequest---file not found");
        }
        mClass = clazz;
        mFilePartNames = new ArrayList<>();
        mFilePartNames.add(filePartName);
        mListener = listener;
        mParams = params;
        this.url = url;

        buildMultipartEntity();

    }

    @Override
    public RetryPolicy getRetryPolicy() {
        return new DefaultRetryPolicy(MY_SOCKET_TIMEOUT_MS,
                DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
                DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
    }


    /**
     * 多个文件＋参数上传
     *
     * @param url
     * @param listener
     * @param errorListener
     * @param filePartName
     * @param files
     * @param params
     */
    public MultipartRequest(String url, Response.Listener<RESULT> listener, Response.ErrorListener errorListener
            , List<String> filePartName, List<File> files, Map<String, String> params, Class<RESULT> clazz) {
        super(Method.POST, url, errorListener);
        mClass = clazz;
        mFilePartNames = filePartName;
        mListener = listener;
        mFileParts = files;
        mParams = params;
        this.url = url;
        buildMultipartEntity();
    }

    @Override
    protected Response<RESULT> parseNetworkResponse(NetworkResponse response) {

        try {

            //parseHeaders(response);//解析头部
            RESULT result = parseData(response);//解析body

            return Response.success(
                    result,
                    HttpHeaderParser.parseCacheHeaders(response));
        } catch (UnsupportedEncodingException e) {
            return Response.error(new ParseError(e));
        } catch (JSONException e) {
            return Response.error(new ParseError(e));
        } /*catch (HeaderCodeError e) {
            return Response.error(e);
		} */


        /*String parsed;
        try {
            parsed = new String(response.data,
                    HttpHeaderParser.parseCharset(response.headers));
        } catch (UnsupportedEncodingException e) {
            parsed = new String(response.data);
        }
        return Response.success(parsed,
                HttpHeaderParser.parseCacheHeaders(response));*/


    }

    protected RESULT parseData(NetworkResponse response) throws UnsupportedEncodingException, JSONException {
        String jsonString = new String(response.data,
                HttpHeaderParser.parseCharset(response.headers));
        JSONObject jo;
        Log.i("juner", "juner NetworkResponse:" + jsonString);
        jo = new JSONObject(jsonString.toString());
        HandleCode.code = Integer.valueOf(jo.getString("code"));
        HandleCode.headerMessage = String.valueOf(jo.getString("message"));
        return GsonHelper.getDeserializer().fromJson(jo.getString("result"), mClass);
    }

    @Override
    public void deliverError(VolleyError error) {
        super.deliverError(error);
        if (error instanceof ParseError) {
            ActivityUtils.toast("解析错误!");
            LogUtils.i("deliverError 解析错误: " + url);
        } else if (error instanceof ServerError) {
            ActivityUtils.toast("服务器错误!");
        } else if (error instanceof NoConnectionError) {
            ActivityUtils.toast("服务器连接失败!");
        } else if (error instanceof HeaderCodeError) {
            if (((HeaderCodeError) error).getStatusCode() == 21013) {
                ActivityUtils.toast("请求错误!");
            } else {


            }
        }
        Log.e("juner", "juner: " + error.toString());
    }

    @Override
    protected void deliverResponse(RESULT response) {
        mListener.onResponse(response);
    }

    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }
        if (UniApplication.getInstance().hasLogin()) {
//            headers.put("TOKEN", UniApplication.getInstance().getUserInfo().getToken());
        }
        return headers;
    }

    /*@Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        HashMap<String, String> headers = new HashMap<String, String>();
        if (UniApplication.getInstance().hasLogin()) {
            headers.put("TOKEN", UniApplication.getInstance().getUserInfo().getToken());
        }
        Log.i("juner", "juner headers:"+headers.toString());
        return headers;
    }*/

    @Override
    public String getBodyContentType() {
        return entity.getContentType().getValue();
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        try {
            entity.writeTo(bos);
        } catch (IOException e) {
            VolleyLog.e("IOException writing to ByteArrayOutputStream");
        }
        return bos.toByteArray();
    }


    private void buildMultipartEntity() {
        if (mFileParts != null && mFileParts.size() > 0) {
            for (int i = 0 ;i < mFileParts.size();i++){
                entity.addPart(mFilePartNames.get(i), new FileBody(mFileParts.get(i)));
            }
//            for (File file : mFileParts) {
//                entity.addPart(mFilePartNames, new FileBody(file));
//            }
            long l = entity.getContentLength();
            LogUtils.i("bruce request "+ mFileParts.size() + "个，长度：" + l);
        }
        LogUtils.i("bruce request url: " + url + " request params: " + GsonHelper.writeValue(mParams));
        try {
            if (mParams != null && mParams.size() > 0) {
                if(!mParams.containsKey("sign"))
                    mParams.put("sign", NetworkUtils.getMacAddress(UniApplication.getInstance()));
                for (Map.Entry<String, String> entry : mParams.entrySet()) {
                    entity.addPart(
                            entry.getKey(),
                            new StringBody(entry.getValue(), Charset
                                    .forName("UTF-8")));
                }

            }
        } catch (UnsupportedEncodingException e) {
            VolleyLog.e("UnsupportedEncodingException");
        }
    }

}